﻿using System;
using UnityEngine;

namespace Nomo.UnityCoreModule
{
    public sealed class OverlappedUniformProgressesCalculator
    {
        private float[] _progresses;
        private int     _size;
        private float   _proportion;
        private float   _totalProgress;

        public OverlappedUniformProgressesCalculator(int size, float proportion)
        {
            if (size < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }
            if (proportion < 0F || proportion > 1F)
            {
                throw new ArgumentOutOfRangeException(nameof(proportion));
            }

            _progresses    = new float[size];
            _size          = size;
            _proportion    = proportion;
            _totalProgress = default;
        }

        public float this[int index] => _progresses[index];

        public int Size
        {
            get => _size;
            set
            {
                if (value == _size)
                {
                    return;
                }
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(value));
                }
                _progresses = new float[value];
                _size       = value;
            }
        }

        public float Proportion
        {
            get => _proportion;
            set
            {
                if (value == _proportion)
                {
                    return;
                }
                if (value < 0F || value > 1F)
                {
                    throw new ArgumentOutOfRangeException(nameof(value));
                }
                _proportion = value;
            }
        }

        public float TotalProgress
        {
            get => _totalProgress;
            set
            {
                if (value == _totalProgress)
                {
                    return;
                }
                if (value < 0F || value > 1F)
                {
                    throw new ArgumentOutOfRangeException(nameof(value));
                }
                _totalProgress = value;
            }
        }

        public void Update()
        {
            if (_size == 0)
            {
                return;
            }
            if (_size == 1)
            {
                _progresses[0] = _totalProgress;
                return;
            }
            if (_proportion == 0F)
            {
                for (var i = 0; i < _size; i++)
                {
                    _progresses[i] = _totalProgress;
                }
                return;
            }
            var value1 = 1F - _proportion;
            var value2 = value1 / (_size - 1);
            for (var i = 0; i < _size; i++)
            {
                var min = value2 * i;
                var max = min + _proportion;
                _progresses[i] = Mathf.InverseLerp(min, max, _totalProgress);
            }
        }
    }
}
